# Gevent monkeypath
from gevent import monkey

monkey.patch_all()

# Gevent imports
import gevent
from gevent import socket

# Python immports
import functools

# Tornado imports
import tornado.ioloop
import tornado.web
import tornado.httpserver

# Request imports
# import requests
import urllib
from tornado.concurrent import Future


# Asynchronous gevent decorator
def gasync(func):
    @tornado.web.asynchronous
    @functools.wraps(func)
    def f(self, *args, **kwargs):
        # self._auto_finish = False
        return gevent.spawn(func, self, *args, **kwargs)

    return f


# Asynchronous gevent decorator
def gfuture(func):
    @functools.wraps(func)
    def f(*args, **kwargs):
        loop = tornado.ioloop.IOLoop.current()
        future = Future()

        def call_method():
            try:
                result = func(*args, **kwargs)
                loop.add_callback(functools.partial(future.set_result, result))
            except Exception, e:
                loop.add_callback(functools.partial(future.set_exception, e))

        gevent.spawn(call_method)
        return future

    return f


# Constants
URL_TO_FETCH = 'http://iot.hifocus.top'

# Global
I = 0


class MainHandler(tornado.web.RequestHandler):
    @gasync
    def get(self):
        global I
        # r = requests.get(URL_TO_FETCH)
        #f = urllib.urlopen(URL_TO_FETCH)
        f = gevent.spawn(socket.gethostbyname, 'localhost')
        print f
        I += 1
        # print('Got page %d (length=%d)' % (I, len(r.content)))
        #self.write("Done")
        #self.finish()


import pymongo
d = pymongo.MongoClient().bora_v2_test.devices
import motor
d_async = motor.MotorClient().bora_v2_test.devices

@gfuture
def gfetch(url, i):
    #gevent.sleep(0.1)
    import time
    time.sleep(0.1)
    # r = d.find_one({'device_id': 123})
    # r = requests.get(url)
    #f = urllib.urlopen(url)
    #r = gevent.spawn(socket.gethostbyname, 'localhost')
    # r = socket.gethostbyname('localhost')
    #print 'gfetch,', r
    #print f.read()
    return i


class MainHandler2(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @tornado.gen.coroutine
    def get(self):
        global I
        I += 1
        n = I
        print "-> %s" % n
        n = yield gfetch(URL_TO_FETCH, n)
        print "<- %s" % n
        self.write("Done %s" % n)

class MainHandler3(tornado.web.RequestHandler):
    @tornado.gen.coroutine
    def get(self):
        global I
        from tornado.gen import sleep
        import time
        I += 1
        n = I
        print "before sleep +> %s" % n
        time.sleep(1)
        print "after sleep +> %s" % n

        yield sleep(0.1)

        print "<+ %s" % n
        #r = yield d_async.find_one({'device_id': 123})
        #print r


class MainHandler4(tornado.web.RequestHandler):
    def get(self):
        import time
        time.sleep(0.1)
        #print r


# Our URL Mappings
handlers = [
    (r"/1", MainHandler),
    (r"/2", MainHandler2),
    (r"/3", MainHandler3),
    (r"/4", MainHandler4),
]

def main():
    # Setup app and HTTP server
    application = tornado.web.Application(handlers)
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(9998)

    # Start ioloop
    tornado.ioloop.IOLoop.instance().start()


if __name__ == "__main__":
    main()
